使用記住存儲對象的 Composable 會創建內部狀態,使可組合項有該狀態。HelloContent 就是一個有狀態的可組合項的示例,因為它會在保持和修改自己的名稱狀態。在調用方的內部不需要狀態,並且必須在狀態下自己管理狀態才能使用但是的情況,“有”重複會非常有用。
無狀態可組合項是指不保持任何狀態的可組合項。實現無狀態的一種簡單方法是使用狀態提升。
在開發可重複使用的可組合項時,您通常希望同時提供相同的狀態可組合項的有和無狀態版本。有版本對於不涉及狀態項的調用方來說很方便,而無狀態版本對於需要控製或提升狀態的調用方說是必需的。
組合中的提升是一種將狀態移動至可組合狀態的調用方以使可組合項的模式。
value: T:要顯示的當前值
onValueChange: (T) -> Unit:請求更改值的事件,其中 T 是建議的新值
如果更具體的事件,可以定義您使用的特定事件的這些值更改。
以這種方式提升的狀態具有一些重要的屬性:
多個來源:狀態,而不是複制,我們可以確保通過一個可靠的狀態來源。
封裝:只有有狀態可組合項其狀態。這完全是內部的。
可共享:可與多個可組合項提升這一狀態。如果想在另一個可組合項中執行名稱,可以通過提升變量來完成點。
事件可阻止決定:在沒有狀態之前可修改組合的調用方可以在狀態更改或承繼。
解耦:無狀態 ExpandingCard 的狀態可以存儲在任何位置。例如,現在可以將名稱移入 ViewModel。
在本本中,您從 HelloContent 中提取名稱和 onValueChange,並按照可組合項的樹結構將它們移動至可調用 HelloContent 的 HelloScreen 可組合項中。
@Composable
fun HelloScreen() {
var name by rememberSaveable { mutableStateOf("") }
HelloContent(name = name, onNameChange = { name = it })
}
@Composable
fun HelloContent(name: String, onNameChange: (String) -> Unit) {
Column(modifier = Modifier.padding(16.dp)) {
Text(
text = "Hello, $name",
modifier = Modifier.padding(bottom = 8.dp),
style = MaterialTheme.typography.h5
)
OutlinedTextField(
value = name,
onValueChange = onNameChange,
label = { Text("Name") }
)
}
}
通過從 HelloContent 中提升出狀態,更容易推斷出該組合項、在不同的情況下您下重複使用它,以及進行。更改 HelloContent 的實現方式。
狀態下降、事件上升的這種模式稱為“單向數據流”。在這種情況下,狀態會從 HelloScreen 下降為 HelloContent,事件會從 HelloContent 上升為 HelloScreen。通過跟踪單向數據流,可以將在項目界面中顯示狀態的可組合與應用中存儲和狀態更改的部分解耦。